/**
 * MCP客户端工具类
 * 处理与MCP工具的通信
 */
const { Client } = require('@modelcontextprotocol/sdk/client');
const { StreamableHTTPClientTransport } = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
const config = require('../config');
const { getAllTools, getToolsByServer } = require('../config/mcp-tools');
const { log } = require('../middleware/logger');

// 确保fetch可用 (Node.js 18+)
if (typeof global.fetch === 'undefined') {
  log.warn('fetch不可用，MCP功能可能受限。请确保Node.js版本18+');
}

class MCPClient {
  constructor() {
    this.tools = new Map();
    this.clients = new Map(); // 存储各个MCP客户端实例
    this.isInitialized = false;
    this.maxRetryCount = 3;
    this.retryDelay = 1000;

    // MCP服务器配置
    const toolConfig = config.mcp.tools;
    this.mcpServers = {
      '12306': {
        name: '12306-mcp',
        url: toolConfig['12306'].url,
        type: 'streamable_http'
      },
      'amap': {
        name: 'amap-maps',
        url: toolConfig.amap.url,
        type: 'streamable_http'
      },
      'weather': {
        name: 'MCP_WEATHER_MCP_Agent_Challenge',
        url: toolConfig.weather.url,
        type: 'streamable_http'
      },
      'time': {
        name: 'time-mcp',
        url: toolConfig.time.url,
        type: 'streamable_http'
      }
    };

    // 初始化工具
    this.initializeTools();
  }

  /**
   * 初始化MCP工具
   */
  async initializeTools() {
    try {
      if (!config.mcp.enabled) {
        log.warn('MCP工具未启用');
        return;
      }

      // 初始化各个MCP服务器的客户端连接
      await this.initializeMCPClients();

      // 使用配置文件注册所有工具
      await this.registerAllTools();

      this.isInitialized = true;
      log.info('MCP工具初始化完成', {
        toolCount: this.tools.size,
        servers: Object.keys(this.mcpServers),
        clients: Array.from(this.clients.keys())
      });

    } catch (error) {
      log.error('MCP工具初始化失败', error);
      throw error;
    }
  }

  /**
   * 初始化MCP客户端连接
   */
  async initializeMCPClients() {
    for (const [serverKey, serverConfig] of Object.entries(this.mcpServers)) {
      try {
        if (!serverConfig.url) {
          log.warn(`跳过MCP服务器 ${serverKey}: 未配置URL`);
          continue;
        }

        // 创建StreamableHTTP传输层
        const transport = new StreamableHTTPClientTransport(
          new URL(serverConfig.url),
          {
            // 重连配置
            reconnectionOptions: {
              maxReconnectionDelay: 30000,
              initialReconnectionDelay: 1000,
              reconnectionDelayGrowFactor: 1.5,
              maxRetries: 3
            }
          }
        );

        // 创建MCP客户端
        const client = new Client({
          name: `travel-assistant-${serverKey}`,
          version: '1.0.0'
        }, {
          capabilities: {
            tools: {}
          }
        });

        // 连接客户端
        await client.connect(transport);

        // 存储客户端实例
        this.clients.set(serverKey, client);

        log.info(`MCP客户端连接成功: ${serverKey}`, {
          url: serverConfig.url,
          name: serverConfig.name
        });

      } catch (error) {
        log.error(`MCP客户端连接失败: ${serverKey}`, {
          error: error.message,
          url: serverConfig.url
        });
        // 继续初始化其他客户端，不中断整个过程
      }
    }
  }

  /**
   * 注册所有工具
   * 使用配置文件中的工具定义
   */
  async registerAllTools() {
    const allTools = getAllTools();

    for (const tool of allTools) {
      this.registerTool(tool.name, tool);
    }

    log.info('所有MCP工具注册完成', {
      totalTools: allTools.length,
      by12306: getToolsByServer('12306').length,
      byAmap: getToolsByServer('amap').length,
      byWeather: getToolsByServer('weather').length,
      byTime: getToolsByServer('time').length
    });
  }

  /**
   * 注册工具
   * @param {string} name - 工具名称
   * @param {Object} definition - 工具定义
   */
  registerTool(name, definition) {
    this.tools.set(name, definition);
    log.debug('注册MCP工具', {
      name,
      description: definition.description,
      server: definition.mcpServer
    });
  }

  /**
   * 获取可用工具列表
   * @returns {Array} 工具列表
   */
  getAvailableTools() {
    return Array.from(this.tools.values());
  }

  /**
   * 调用MCP工具
   * @param {string} toolName - 工具名称
   * @param {Object} parameters - 工具参数
   * @returns {Promise<Object>} 工具执行结果
   */
  async callTool(toolName, parameters) {
    try {
      if (!this.isInitialized) {
        throw new Error('MCP客户端未初始化');
      }

      const tool = this.tools.get(toolName);
      if (!tool) {
        throw new Error(`未找到工具: ${toolName}`);
      }

      log.info('调用MCP工具', {
        toolName,
        parameters,
        server: tool.mcpServer
      });

      // 验证参数
      this.validateParameters(tool, parameters);

      // 调用对应的MCP服务器
      const result = await this.callMCPServer(tool.mcpServer, toolName, parameters);
      log.info('MCP工具调用结果', {
        toolName,
        result
      })

      return {
        success: true,
        data: result
      };

    } catch (error) {
      log.error('MCP工具调用失败', {
        toolName,
        error: error.message,
        parameters
      });

      return {
        success: false,
        error: {
          message: error.message,
          code: 'MCP_CALL_ERROR',
          toolName
        }
      };
    }
  }

  /**
   * 调用MCP服务器
   * @param {string} serverName - 服务器名称
   * @param {string} toolName - 工具名称
   * @param {Object} parameters - 参数
   * @returns {Promise<Object>} 调用结果
   */
  async callMCPServer(serverName, toolName, parameters) {
    const client = this.clients.get(serverName);
    if (!client) {
      throw new Error(`未找到MCP客户端: ${serverName}`);
    }

    try {
      // 使用SDK的callTool方法调用工具
      const result = await client.callTool({
        name: toolName,
        arguments: parameters || {}
      });

      // 处理工具调用结果
      if (result.isError) {
        throw new Error(`工具调用失败: ${result.content[0]?.text || '未知错误'}`);
      }

      // 提取结果内容
      let content = null;
      if (result.content && result.content.length > 0) {
        const firstContent = result.content[0];
        if (firstContent.type === 'text') {
          try {
            // 尝试解析JSON
            content = JSON.parse(firstContent.text);
          } catch {
            // 如果不是JSON，直接返回文本
            content = firstContent.text;
          }
        } else {
          content = firstContent;
        }
      }

      return content;

    } catch (error) {
      log.error('MCP服务器调用失败', {
        serverName,
        toolName,
        error: error.message
      });
      throw error;
    }
  }

  /**
   * 验证工具参数
   * @param {Object} tool - 工具定义
   * @param {Object} parameters - 参数
   */
  validateParameters(tool, parameters) {
    const { required = [] } = tool.parameters;

    for (const param of required) {
      if (!parameters.hasOwnProperty(param)) {
        throw new Error(`缺少必需参数: ${param}`);
      }
    }
  }

  /**
   * 获取连接状态
   * @returns {Object} 连接状态信息
   */
  getConnectionStatus() {
    return {
      initialized: this.isInitialized,
      toolCount: this.tools.size,
      enabled: config.mcp.enabled,
      servers: Object.keys(this.mcpServers),
      connectedClients: Array.from(this.clients.keys()),
      tools: Array.from(this.tools.keys())
    };
  }

  /**
   * 关闭所有MCP客户端连接
   */
  async close() {
    try {
      for (const [serverKey, client] of this.clients.entries()) {
        try {
          await client.close();
          log.info(`MCP客户端已关闭: ${serverKey}`);
        } catch (error) {
          log.error(`关闭MCP客户端失败: ${serverKey}`, error);
        }
      }
      this.clients.clear();
      this.isInitialized = false;
    } catch (error) {
      log.error('关闭MCP客户端失败', error);
      throw error;
    }
  }
}

// 创建单例实例
const mcpClient = new MCPClient();

module.exports = mcpClient;